import HDWallet from 'react-native-hdwallet';
import walletUtils from 'react-native-hdwallet/src/utils/walletUtils';
import StorageManager, {WALLET_LIST, walletType} from '../../storage/index';
import KeystoreUtils from './KeystoreUtils';
import keythereum from 'keythereum';
import config from '../chain/config';
import ChainUtils from '../chain/ChainUtils';
import {
  erc20Abi,
  nftAbi,
  swhtAbi,
  auctionProxyAbi,
  clubAbi,
} from '../chain/contract';
import BigNumber from 'bignumber.js';

//chain对象
let chain = new ChainUtils();

export default class WalletUtils {
  static async initWeb3(url) {
    chain.setUrl(url);
  }

  /**
   * gengral keystore by password
   * @param {*} password
   * @returns
   */
  static async generalWallet(password) {
    try {
      let mnemonic = await walletUtils.generateMnemonic();
      console.log('生成的助记词');
      console.log(mnemonic);

      const seed = walletUtils.mnemonicToSeed(mnemonic);
      // const seedHex = seed.toString('hex');
      const hdwallet = HDWallet.fromMasterSeed(seed);
      const derivePath = "m/44'/60'/0'/0/0";
      hdwallet.setDerivePath(derivePath);
      var privateKey = hdwallet.getPrivateKey();
      var address = hdwallet.getChecksumAddressString();
      console.log('address---' + address);

      //根据私钥和密码导入到本地
      const params = {keyBytes: 32, ivBytes: 16};
      const dk = keythereum.create(params);

      const keystore = await KeystoreUtils.dump(
        password,
        privateKey,
        dk.salt,
        dk.iv,
      );
      return {
        keystore,
        address,
      };
    } catch (err) {
      console.log('生成助记词失败' + err);
      return err;
    }
  }

  /**
   * privateKey of keystore
   * @param {*} keystore
   * @param {*} password
   * @returns
   */
  static async privateKeyOfKeystore(keystore, password) {
    keystore = typeof keystore == 'string' ? JSON.parse(keystore) : keystore;
    const privateKey = await KeystoreUtils.recover(password, keystore);
    return `0x${privateKey.toString('hex')}`;
  }

  /**
   * erc20 balance
   * @param {*} address
   * @param {*} contractAddress
   * @param {*} decimal
   * @returns
   */
  static async queryTokenBalance(address, contractAddress, decimal) {
    const ether = new BigNumber(Math.pow(10, decimal));

    const bigBalance = new BigNumber(
      await chain.sendContractCallTransaction(
        erc20Abi,
        contractAddress,
        'balanceOf',
        [address],
      ),
    );
    let vAmount = parseFloat(bigBalance.dividedBy(ether));
    return ChainUtils.subStringNum(vAmount, 4);
  }

  /**
   * gas coin balance
   * @param {*} address
   * @returns
   */
  static async queryAccountHecoBalance(address) {
    return chain.balanceOf(address);
  }

  /**
   * 发送heco
   * @param {*} toAddress
   * @param {*} amount
   */
  static async transferHeco(privateKey, toAddress, amount, hashCall) {
    chain.addPrivateKey(privateKey);

    return new Promise((resolve, reject) => {
      chain.sendETHTransaction(toAddress, amount, null, null, (hash, err) => {
        if (hash) {
          hashCall && hashCall(hash);

          console.log('已发送交易' + hash);
          chain.listenTrx(
            hash,
            (tx) => {
              resolve(tx);
            },
            () => {
              reject('交易上链超时');
            },
          );
        } else {
          console.log(err);
          reject(err);
        }
      });
    });
  }

  //==================   ERC20  ========================//
  /**
   * erc20 allowance amount
   * @param {*} _owner 授权人
   * @param {*} spender 被授权人
   * @param {*} contractAddress
   * @param {*} decimal
   * @returns
   */
  static async queryTokenAllowance(owner, spender, contractAddress, decimal) {
    const ether = new BigNumber(Math.pow(10, decimal));

    const bigBalance = new BigNumber(
      await chain.sendContractCallTransaction(
        erc20Abi,
        contractAddress,
        'allowance',
        [owner, spender],
      ),
    );
    let vAmount = parseFloat(bigBalance.dividedBy(ether));
    return ChainUtils.subStringNum(vAmount, 4);
  }

  /**
   * 发送erc20代币
   * @param {*} privateKey
   * @param {*} toAddress
   * @param {*} amount
   * @param {*} contractAddress
   * @param {*} decimal
   */
  static async transferErc20(
    privateKey,
    toAddress,
    amount,
    contractAddress,
    decimal,
    hashCall,
  ) {
    chain.addPrivateKey(privateKey);

    return new Promise((resolve, reject) => {
      amount = new BigNumber(amount * Math.pow(10, decimal));
      let ratio = new BigNumber(10);
      amount = amount.dividedToIntegerBy(ratio).multipliedBy(ratio);
      let params = [toAddress, '0x' + amount.toString(16)];
      console.log(params);

      chain.sendContractFunctionTransaction(
        erc20Abi,
        contractAddress,
        'transfer',
        params,
        null,
        null,
        (hash, err) => {
          if (hash) {
            hashCall && hashCall(hash);
            console.log('已发送交易' + hash);
            chain.listenTrx(
              hash,
              (tx) => {
                resolve(tx);
              },
              () => {
                reject('交易上链超时');
              },
            );
          } else {
            console.log(err);
            reject(err);
          }
        },
      );
    });
  }

  /**
   * erc20代币授权
   * @param {*} privateKey
   * @param {*} toAddress
   * @param {*} amount
   * @param {*} contractAddress
   * @param {*} decimal
   */
  static async approve(
    privateKey,
    contractAddress,
    toAddress,
    amount,
    decimal,
    hashCall,
  ) {
    chain.addPrivateKey(privateKey);

    return new Promise((resolve, reject) => {
      amount = new BigNumber(amount * Math.pow(10, 18));
      let ratio = new BigNumber(10);
      amount = amount.dividedToIntegerBy(ratio).multipliedBy(ratio);
      let params = [toAddress, '0x' + amount.toString(16)];
      console.log(params);

      chain.sendContractFunctionTransaction(
        erc20Abi,
        contractAddress,
        'approve',
        params,
        null,
        null,
        (hash, err) => {
          if (hash) {
            hashCall && hashCall(hash);
            console.log('已发送交易' + hash);
            chain.listenTrx(
              hash,
              (tx) => {
                resolve(tx);
              },
              () => {
                reject('交易上链超时');
              },
            );
          } else {
            console.log('----');
            console.log(err);
            reject(err);
          }
        },
      );
    });
  }

  /**
   * 获取erc20代币授权的交易
   * @param {*} privateKey
   * @param {*} toAddress
   * @param {*} amount
   * @param {*} contractAddress
   * @param {*} decimal
   */
  static async getApproveTx(
    contractAddress,
    toAddress,
    amount,
    decimal = 18,
    from,
  ) {
    amount = new BigNumber(amount * Math.pow(10, decimal));
    let ratio = new BigNumber(10);
    amount = amount.dividedToIntegerBy(ratio).multipliedBy(ratio);
    let params = [toAddress, '0x' + amount.toString(16)];
    console.log(params);

    return chain.getContractFunctionTransaction(
      erc20Abi,
      contractAddress,
      'approve',
      params,
      null,
      null,
      from,
    );
  }

  //==================   SWHT  ========================//

  /**
   * 计算交易gas费用
   */
  static async getSwapTxGasPrice() {
    try {
      let gas = await chain.getTxGasPrice(
        ChainUtils.TransferGasLimit.swapGasLimit,
      );
      return Promise.resolve(gas);
    } catch (err) {
      console.log(err);
      console.log('获取gas失败');
      return Promise.resolve(0);
    }
  }

  /**
   * 发送swap的heco
   * @param {*} toAddress
   * @param {*} amount
   */
  static async transferSwapHt(privateKey, toAddress, amount, hashCall) {
    chain.addPrivateKey(privateKey);

    return new Promise((resolve, reject) => {
      chain.sendETHTransaction(
        toAddress,
        amount,
        null,
        ChainUtils.TransferGasLimit.swapGasLimit,
        (hash, err) => {
          if (hash) {
            hashCall && hashCall(hash);

            console.log('已发送交易' + hash);
            chain.listenTrx(
              hash,
              (tx) => {
                resolve(tx);
              },
              () => {
                reject('交易上链超时');
              },
            );
          } else {
            console.log(err);
            reject(err);
          }
        },
      );
    });
  }

  /**
   * swht提现
   * @param {*} toAddress
   * @param {*} amount
   */
  static async withdrawSWHT(
    privateKey,
    contractAddress,
    toAddress,
    amount,
    hashCall,
  ) {
    chain.addPrivateKey(privateKey);

    return new Promise((resolve, reject) => {
      amount = new BigNumber(amount * Math.pow(10, 18));
      let ratio = new BigNumber(10);
      amount = amount.dividedToIntegerBy(ratio).multipliedBy(ratio);
      let params = ['0x' + amount.toString(16), toAddress];
      console.log(params);

      chain.sendContractFunctionTransaction(
        swhtAbi,
        contractAddress,
        'withdraw',
        params,
        null,
        null,
        (hash, err) => {
          if (hash) {
            hashCall && hashCall(hash);

            console.log('已发送交易' + hash);
            chain.listenTrx(
              hash,
              (tx) => {
                resolve(tx);
              },
              () => {
                reject('交易上链超时');
              },
            );
          } else {
            console.log(err);
            reject(err);
          }
        },
      );
    });
  }

  //==================   Club  ========================//

  /**
   * 计算交易gas费用
   */
  static async getRegisterClubGasPrice() {
    try {
      let gas = await chain.getTxGasPrice(
        ChainUtils.TransferGasLimit.tokenGasLimit,
      );
      return Promise.resolve(gas);
    } catch (err) {
      console.log(err);
      console.log('获取gas失败');
      return Promise.resolve(0);
    }
  }

  static async registerClub(privateKey, contractAddress, hashCall) {
    chain.addPrivateKey(privateKey);

    return new Promise((resolve, reject) => {
      let params = [];

      chain.sendContractFunctionTransaction(
        clubAbi,
        contractAddress,
        'register',
        params,
        null,
        ChainUtils.TransferGasLimit.extraFuncGasLimit,
        (hash, err) => {
          if (hash) {
            hashCall && hashCall(hash);

            console.log('已发送交易' + hash);
            chain.listenTrx(
              hash,
              (tx) => {
                resolve(tx);
              },
              () => {
                reject('交易上链超时');
              },
            );
          } else {
            console.log(err);
            reject(err);
          }
        },
      );
    });
  }

  //==================   NFT  ========================//

  /**
   * 计算交易gas费用
   */
  static async getRegisterNFTGasPrice() {
    try {
      let gas = await chain.getTxGasPrice(
        ChainUtils.TransferGasLimit.tokenGasLimit,
      );
      return Promise.resolve(gas);
    } catch (err) {
      console.log(err);
      console.log('获取gas失败');
      return Promise.resolve(0);
    }
  }

  /**
   * erc20 allowance amount
   * @param {*} tokenId 授权人
   * @param {*} spender 被授权人
   * @param {*} contractAddress
   * @param {*} decimal
   * @returns
   */
  static async queryNFTApproveAddress(tokenId, contractAddress) {
    return chain.sendContractCallTransaction(
      nftAbi,
      contractAddress,
      'getApproved',
      [tokenId],
    );
  }

  /**
   * 创建nft资源
   * @param {*} privateKey
   * @param {*} contractAddress
   * @param {*} tokenId
   * @param {*} owner
   */
  static async registerNFT(
    privateKey,
    contractAddress,
    tokenId,
    owner,
    hashCall,
  ) {
    chain.addPrivateKey(privateKey);

    return new Promise((resolve, reject) => {
      let params = [owner, tokenId];

      chain.sendContractFunctionTransaction(
        nftAbi,
        contractAddress,
        'mint',
        params,
        null,
        ChainUtils.TransferGasLimit.extraFuncGasLimit,
        (hash, err) => {
          if (hash) {
            hashCall && hashCall(hash);

            console.log('已发送交易' + hash);
            chain.listenTrx(
              hash,
              (tx) => {
                resolve(tx);
              },
              () => {
                reject('交易上链超时');
              },
            );
          } else {
            console.log(err);
            reject(err);
          }
        },
      );
    });
  }

  /**
   * 生成创建nft资源的TX
   * @param {*} contractAddress
   * @param {*} tokenId
   * @param {*} owner
   */
  static async getRegisterNFTTx(contractAddress, tokenId, owner, from) {
    let params = [owner, tokenId];
    return chain.getContractFunctionTransaction(
      nftAbi,
      contractAddress,
      'mint',
      params,
      null,
      ChainUtils.TransferGasLimit.extraFuncGasLimit,
      from,
    );
  }

  /**
   * 授权nft转让
   * @param {*} privateKey
   * @param {*} contractAddress
   * @param {*} to
   * @param {*} tokenId
   */
  static async approveNFT(privateKey, contractAddress, to, tokenId, hashCall) {
    chain.addPrivateKey(privateKey);

    return new Promise((resolve, reject) => {
      let params = [to, tokenId];

      chain.sendContractFunctionTransaction(
        nftAbi,
        contractAddress,
        'approve',
        params,
        null,
        ChainUtils.TransferGasLimit.tokenGasLimit,
        (hash, err) => {
          if (hash) {
            hashCall && hashCall(hash);

            console.log('已发送交易' + hash);
            chain.listenTrx(
              hash,
              (tx) => {
                resolve(tx);
              },
              () => {
                reject('交易上链超时');
              },
            );
          } else {
            console.log(err);
            reject(err);
          }
        },
      );
    });
  }

  /**
   * 获取授权nft转让交易
   * @param {*} contractAddress
   * @param {*} to
   * @param {*} tokenId
   */
  static async getApproveNFTTx(contractAddress, to, tokenId, from) {
    let params = [to, tokenId];
    return chain.getContractFunctionTransaction(
      nftAbi,
      contractAddress,
      'approve',
      params,
      null,
      ChainUtils.TransferGasLimit.tokenGasLimit,
      from,
    );
  }

  //==================   AuctionProxy  ========================//

  /**
   * 创建拍卖
   * @param {*} toAddress
   * @param {*} amount
   */
  static async createAuction(
    privateKey,
    contractAddress,
    nftAddess,
    tokenId,
    payCoinAddress,
    startPrice,
    miniIncreasePrice,
    maxPrice,
    expireDate,
    from,
    decimal,
    hashCall,
  ) {
    chain.addPrivateKey(privateKey);

    return new Promise((resolve, reject) => {
      let ratio = new BigNumber(10);

      startPrice = new BigNumber(startPrice * Math.pow(10, decimal));
      startPrice = startPrice.dividedToIntegerBy(ratio).multipliedBy(ratio);

      miniIncreasePrice = new BigNumber(
        miniIncreasePrice * Math.pow(10, decimal),
      );
      miniIncreasePrice = miniIncreasePrice
        .dividedToIntegerBy(ratio)
        .multipliedBy(ratio);

      maxPrice = new BigNumber(maxPrice * Math.pow(10, decimal));
      maxPrice = maxPrice.dividedToIntegerBy(ratio).multipliedBy(ratio);

      let params = [
        nftAddess,
        tokenId,
        payCoinAddress,
        '0x' + startPrice.toString(16),
        '0x' + miniIncreasePrice.toString(16),
        '0x' + maxPrice.toString(16),
        expireDate,
        from,
      ];

      chain.sendContractFunctionTransaction(
        auctionProxyAbi,
        contractAddress,
        'createAuction',
        params,
        null,
        ChainUtils.TransferGasLimit.extraFuncGasLimit,
        (hash, err) => {
          if (hash) {
            hashCall && hashCall(hash);

            console.log('已发送交易' + hash);
            chain.listenTrx(
              hash,
              (tx) => {
                resolve(tx);
              },
              () => {
                reject('交易上链超时');
              },
            );
          } else {
            console.log(err);
            reject(err);
          }
        },
      );
    });
  }

  /**
   * 获取创建拍卖的交易
   * @param {*} toAddress
   * @param {*} amount
   */
  static async getCreateAuctionTx(
    contractAddress,
    nftAddess,
    tokenId,
    payCoinAddress,
    startPrice,
    miniIncreasePrice,
    maxPrice,
    expireDate,
    from,
    decimal,
    fromAddress,
  ) {
    let ratio = new BigNumber(10);

    startPrice = new BigNumber(startPrice * Math.pow(10, decimal));
    startPrice = startPrice.dividedToIntegerBy(ratio).multipliedBy(ratio);

    miniIncreasePrice = new BigNumber(
      miniIncreasePrice * Math.pow(10, decimal),
    );
    miniIncreasePrice = miniIncreasePrice
      .dividedToIntegerBy(ratio)
      .multipliedBy(ratio);

    maxPrice = new BigNumber(maxPrice * Math.pow(10, decimal));
    maxPrice = maxPrice.dividedToIntegerBy(ratio).multipliedBy(ratio);

    let params = [
      nftAddess,
      tokenId,
      payCoinAddress,
      '0x' + startPrice.toString(16),
      '0x' + miniIncreasePrice.toString(16),
      '0x' + maxPrice.toString(16),
      expireDate,
      from,
    ];

    return chain.getContractFunctionTransaction(
      auctionProxyAbi,
      contractAddress,
      'createAuction',
      params,
      null,
      ChainUtils.TransferGasLimit.extraFuncGasLimit,
      fromAddress,
    );
  }

  /**
   * 计算交易gas费用
   */
  static async getCreateAuctionGasPrice() {
    try {
      let gas = await chain.getTxGasPrice(
        ChainUtils.TransferGasLimit.extraFuncGasLimit,
      );
      return Promise.resolve(gas);
    } catch (err) {
      console.log(err);
      console.log('获取gas失败');
      return Promise.resolve(0);
    }
  }

  /**
   * 出价
   * @param {*} privateKey
   * @param {*} contractAddress
   * @param {*} nftAddess
   * @param {*} tokenId
   * @param {*} value
   * @param {*} from
   * @param {*} payCoinAddress
   * @param {*} decimal
   * @param {*} hashCall
   * @returns
   */
  static async bid(
    privateKey,
    contractAddress,
    nftAddess,
    tokenId,
    value,
    from,
    payCoinAddress,
    decimal,
    hashCall,
  ) {
    chain.addPrivateKey(privateKey);

    return new Promise((resolve, reject) => {
      let ratio = new BigNumber(10);
      value = new BigNumber(value * Math.pow(10, decimal));
      value = value.dividedToIntegerBy(ratio).multipliedBy(ratio);

      let params = [nftAddess, tokenId, '0x' + value.toString(16), from];

      try {
        if (payCoinAddress == '0x0000000000000000000000000000000000000000') {
          chain.sendContractFunctionTransactionWithValue(
            auctionProxyAbi,
            contractAddress,
            'bid',
            params,
            null,
            ChainUtils.TransferGasLimit.extraFuncGasLimit,
            (hash, err) => {
              if (hash) {
                hashCall && hashCall(hash);

                console.log('已发送交易' + hash);
                chain.listenTrx(
                  hash,
                  (tx) => {
                    resolve(tx);
                  },
                  () => {
                    reject('交易上链超时');
                  },
                );
              } else {
                console.log(err);
                reject(err);
              }
            },
            value,
          );
        } else {
          chain.sendContractFunctionTransaction(
            auctionProxyAbi,
            contractAddress,
            'bid',
            params,
            null,
            ChainUtils.TransferGasLimit.extraFuncGasLimit,
            (hash, err) => {
              if (hash) {
                hashCall && hashCall(hash);

                console.log('已发送交易' + hash);
                chain.listenTrx(
                  hash,
                  (tx) => {
                    resolve(tx);
                  },
                  () => {
                    reject('交易上链超时');
                  },
                );
              } else {
                console.log(err);
                reject(err);
              }
            },
          );
        }
      } catch (err) {
        reject({
          err: err,
          params,
        });
      }
    });
  }

  /**
   * 出价
   * @param {*} contractAddress
   * @param {*} nftAddess
   * @param {*} tokenId
   * @param {*} value
   * @param {*} from
   * @param {*} payCoinAddress
   * @param {*} decimal
   * @param {*} hashCall
   * @returns
   */
  static async getBidTx(
    contractAddress,
    nftAddess,
    tokenId,
    value,
    from,
    payCoinAddress,
    decimal,
    fromAddress,
  ) {
    let ratio = new BigNumber(10);
    value = new BigNumber(value * Math.pow(10, decimal));
    value = value.dividedToIntegerBy(ratio).multipliedBy(ratio);
    value = '0x' + value.toString(16);

    let params = [nftAddess, tokenId, value, from];

    try {
      if (payCoinAddress == '0x0000000000000000000000000000000000000000') {
        return chain.getContractFunctionTransactionWithValue(
          auctionProxyAbi,
          contractAddress,
          'bid',
          params,
          null,
          ChainUtils.TransferGasLimit.extraFuncGasLimit,
          value,
          fromAddress,
        );
      } else {
        return chain.getContractFunctionTransaction(
          auctionProxyAbi,
          contractAddress,
          'bid',
          params,
          null,
          ChainUtils.TransferGasLimit.extraFuncGasLimit,
          fromAddress,
        );
      }
    } catch (err) {
      return null;
    }
  }

  /**
   * 同意出价
   * @param {*} privateKey
   * @param {*} contractAddress
   * @param {*} nftAddess
   * @param {*} tokenId
   * @param {*} hashCall
   * @returns
   */
  static async acceptPrice(
    privateKey,
    contractAddress,
    nftAddess,
    tokenId,
    hashCall,
  ) {
    chain.addPrivateKey(privateKey);

    return new Promise((resolve, reject) => {
      let params = [nftAddess, tokenId];

      chain.sendContractFunctionTransaction(
        auctionProxyAbi,
        contractAddress,
        'acceptPrice',
        params,
        null,
        ChainUtils.TransferGasLimit.extraFuncGasLimit,
        (hash, err) => {
          if (hash) {
            hashCall && hashCall(hash);

            console.log('已发送交易' + hash);
            chain.listenTrx(
              hash,
              (tx) => {
                resolve(tx);
              },
              () => {
                reject('交易上链超时');
              },
            );
          } else {
            console.log(err);
            reject(err);
          }
        },
      );
    });
  }

  /**
   * 获取同意出价交易
   * @param {*} contractAddress
   * @param {*} nftAddess
   * @param {*} tokenId
   * @param {*} hashCall
   * @returns
   */
  static async getAcceptPriceTx(contractAddress, nftAddess, tokenId, from) {
    let params = [nftAddess, tokenId];

    return chain.getContractFunctionTransaction(
      auctionProxyAbi,
      contractAddress,
      'acceptPrice',
      params,
      null,
      ChainUtils.TransferGasLimit.extraFuncGasLimit,
      from,
    );
  }

  /**
   * 拒绝出价
   * @param {*} privateKey
   * @param {*} contractAddress
   * @param {*} nftAddess
   * @param {*} tokenId
   * @param {*} hashCall
   * @returns
   */
  static async rejectPrice(
    privateKey,
    contractAddress,
    nftAddess,
    tokenId,
    hashCall,
  ) {
    chain.addPrivateKey(privateKey);

    return new Promise((resolve, reject) => {
      let params = [nftAddess, tokenId];

      chain.sendContractFunctionTransaction(
        auctionProxyAbi,
        contractAddress,
        'refuseOutSaleAuctionBid',
        params,
        null,
        ChainUtils.TransferGasLimit.extraFuncGasLimit,
        (hash, err) => {
          if (hash) {
            hashCall && hashCall(hash);

            console.log('已发送交易' + hash);
            chain.listenTrx(
              hash,
              (tx) => {
                resolve(tx);
              },
              () => {
                reject('交易上链超时');
              },
            );
          } else {
            console.log(err);
            reject(err);
          }
        },
      );
    });
  }

  /**
   * 获取拒绝出价交易
   * @param {*} contractAddress
   * @param {*} nftAddess
   * @param {*} tokenId
   * @param {*} hashCall
   * @returns
   */
  static async getRejectPriceTx(contractAddress, nftAddess, tokenId, from) {
    let params = [nftAddess, tokenId];
    return chain.getContractFunctionTransaction(
      auctionProxyAbi,
      contractAddress,
      'refuseOutSaleAuctionBid',
      params,
      null,
      ChainUtils.TransferGasLimit.extraFuncGasLimit,
      from,
    );
  }

  /**
   * 接受出价
   * @param {*} privateKey
   * @param {*} contractAddress
   * @param {*} nftAddess
   * @param {*} tokenId
   * @param {*} hashCall
   * @returns
   */
  static async agreeOutSaleAuctionBid(
    privateKey,
    contractAddress,
    nftAddess,
    tokenId,
    hashCall,
  ) {
    chain.addPrivateKey(privateKey);

    return new Promise((resolve, reject) => {
      let params = [nftAddess, tokenId];

      chain.sendContractFunctionTransaction(
        auctionProxyAbi,
        contractAddress,
        'agreeOutSaleAuctionBid',
        params,
        null,
        ChainUtils.TransferGasLimit.extraFuncGasLimit,
        (hash, err) => {
          if (hash) {
            hashCall && hashCall(hash);

            console.log('已发送交易' + hash);
            chain.listenTrx(
              hash,
              (tx) => {
                resolve(tx);
              },
              () => {
                reject('交易上链超时');
              },
            );
          } else {
            console.log(err);
            reject(err);
          }
        },
      );
    });
  }

  /**
   * 获取接受出价的交易
   * @param {*} contractAddress
   * @param {*} nftAddess
   * @param {*} tokenId
   * @param {*} hashCall
   * @returns
   */
  static async getAgreeOutSaleAuctionBidTx(
    contractAddress,
    nftAddess,
    tokenId,
    from,
  ) {
    let params = [nftAddess, tokenId];

    return chain.getContractFunctionTransaction(
      auctionProxyAbi,
      contractAddress,
      'agreeOutSaleAuctionBid',
      params,
      null,
      ChainUtils.TransferGasLimit.extraFuncGasLimit,
      from,
    );
  }

  /**
   * 交易上链
   * @param {} hash
   * @returns
   */
  static async listenTx(hash) {
    return new Promise((resolve, reject) => {
      chain.listenTrx(
        hash,
        (tx) => {
          resolve(tx);
        },
        () => {
          reject('failed');
        },
      );
    });
  }
}
